/*
 * cmdline.c
 *
 *  Created on: 2013. 7. 24.
 *      Author: Shim
 */

/* Includes ------------------------------------------------------------------*/
#include "cmdline.h"
#include "usbstdio.h"
#include <string.h>

/* Exported variables --------------------------------------------------------*/

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** 허용할 수 있는 인자의 최대 갯수를 정의한다. */
#ifndef CMDLINE_MAX_ARGS
#define CMDLINE__MAX_ARGS		16
#endif
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
COMMAND_LINE_ENTRY cmdTable[MAX_CMDLINE_SIZE];
int32_t numberOfRegisteredCmdline = 0;
/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

int32_t cmdLineProcess(int8_t *cmdLine)
{
	static int8_t 	*argv[CMDLINE__MAX_ARGS + 1];	/**< 문자열의 갯수는 최대 인자수 + 1개 만큼 */
	int8_t 			*ch;
	int32_t 		argc;
	int32_t			findArg = 1;
	COMMAND_LINE_ENTRY *cmdlineEntry;

	/**
	 * 인자의 개수와 문자열을 가리키는 포인터를 초기화한다.
	 */
	argc = 0;
	ch = cmdLine;

	/** 문자열의 끝까지 주소 포인터를 1씩 증가시키면서 스캔한다. */
	while(*ch) {
		/**
		 * 공백이 있으면 여기까지가 하나의 인자로 취급하고\0으로 치환한다.
		 * 다음 인자를 찾기 위해 flag를 1로 셋한다.
		 */
		if(*ch == ' ') {
			*ch = 0;
			findArg = 1;
		} else {	/**< 공백이 아니면 인자의 문자열에 포함시킨다. */
			/**
			 * 만일 findArg가 셋되어 있으면 다음 인자를 찾는다는 의미이다.
			 */
			if(findArg) {
				if(argc < CMDLINE__MAX_ARGS) {
					argv[argc] = ch;
					argc++;
					findArg = 0;
				} else {
					return (CMDLINE_TOO_MANY_ARGS);
				}
			}
		}

		ch++;
	}

	if(argc) {
		cmdlineEntry = &cmdTable[0];

		while(cmdlineEntry->cmd != 0) {
			if(!strcmp((const char *)argv[0], (const char *)cmdlineEntry->cmd)) {
				return(cmdlineEntry->callback(argc, argv));
			}

			cmdlineEntry++;
		}
	}

	return (CMDLINE_BAD_CMD);
}

int32_t registerCmdline(const int8_t *cmd, CmdLineFunc callback, const int8_t *help)
{
	cmdTable[numberOfRegisteredCmdline].cmd = cmd;
	cmdTable[numberOfRegisteredCmdline].callback = callback;
	cmdTable[numberOfRegisteredCmdline].help = help;

	numberOfRegisteredCmdline++;

	cmdTable[numberOfRegisteredCmdline].cmd = 0;
	cmdTable[numberOfRegisteredCmdline].callback = 0;
	cmdTable[numberOfRegisteredCmdline].help = 0;

	return 0;
}

int32_t cmdHelp(int32_t argc, int8_t *argv[])
{
	COMMAND_LINE_ENTRY *entry;

	usbPrintf((int8_t*)"\n=============================================================\n");
	usbPrintf((int8_t*)"\nAvailable commands\n");
	usbPrintf((int8_t*)"-------------------\n");

	entry = &cmdTable[0];

	while(entry->cmd) {
		usbPrintf((int8_t*)"%s\t : %s\n", entry->cmd, entry->help);
		entry++;
	}
	return 0;
}
